package ca.etsmtl.gti785.servlet;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import ca.etsmtl.gti785.util.Constants;
import ca.etsmtl.gti785.util.Fichier;
import com.google.gson.Gson;

/**
 * This servlet is used to transfer files to a server to another one.
 * @author Étienne Faucher, Pierre-Mary Bien-Aimé
 */
@WebServlet(urlPatterns="/server/fileTransfer", asyncSupported=true)
public class FileTransfer extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
    public FileTransfer() 
    {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		PrintWriter out = response.getWriter();
		out.println("{\"port\":");
		out.println(String.valueOf(Constants.Socket_Server));
		out.println("}");
		response.setStatus(HttpServletResponse.SC_OK);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		AsyncContext asyncContext = request.startAsync();
		asyncContext.setTimeout(Constants.Timeout_delay);
		
		String fileTransfertJsonString = request.getParameter("body");
		Gson gson = new Gson();
		FileTransferJson fichiers1 = gson.fromJson(fileTransfertJsonString, FileTransferJson.class);

		URL serveurDistant;
		HttpURLConnection conn;
		BufferedReader rd;
		String line;		
		String portNumberLine = "";
		int portNumber;
		
		serveurDistant = new URL(fichiers1.url);
		//On a maintenant le fichier et le url : json.url et json.fileServer.
		try 
		{
			conn = (HttpURLConnection) serveurDistant.openConnection();
			conn.setRequestMethod("GET");
			rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			while ((line = rd.readLine()) != null) 
			{
				portNumberLine += line;
			}
			rd.close();
		} catch (IOException e) 
		{
			e.printStackTrace();
		} catch (Exception e) 
		{
			e.printStackTrace();
		}	
		
		JSONObject jsonPort = new JSONObject(portNumberLine);
		portNumber =  jsonPort.getInt("port");

        TransfererFichiers(fichiers1.fileServer, serveurDistant.getHost(), portNumber);
	}
	
	private boolean sendBySocket(Fichier fichier, String host, int port)
	{
			try 
			{
				System.out.println("Trying to send "  + fichier.path + " ...");
				File myFile = new File(Constants.Shared_Folder + fichier.path);
				if(myFile.exists())
				{
					Socket socket = new Socket(host, port);
					byte[] mybytearray = new byte[(int) myFile.length()];
					OutputStream os = socket.getOutputStream();
					ObjectOutputStream oos = new ObjectOutputStream(os);
					oos.writeObject(fichier.path);
					
					BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
					bis.read(mybytearray, 0, mybytearray.length);
					os.write(mybytearray, 0, mybytearray.length);
					
					os.flush();
					oos.close();
					bis.close();
					socket.close();
					System.out.println("File sent !");
				}
			} 
			catch (UnknownHostException e) 
			{
				e.printStackTrace();
				return false;
			} 
			catch (IOException e) 
			{
				e.printStackTrace();
				return false;
			}
			
			return true;
	}

	private void TransfererFichiers(Fichier file, String url, int portNumber)
	{
		if(file.isFolder)
		{
			for(Fichier fichier: file.listFichiers)
			{
				TransfererFichiers(fichier, url, portNumber);
			}
		}
		else
		{
			sendBySocket(file, url, portNumber);
		}
	}
}
